package descentFly.server
{
//	import com.adobe.serialization.json.JSON;
	
	import UIFree.ObjectEvent;
	import UIFree.uif_Timer;
	
	import flash.errors.IOError;
	import flash.events.*;
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	import flash.net.Socket;
	
	import org.osmf.events.TimeEvent;

	
	public class mySocket extends Socket {
		public static const RESPONSE_JSON		: String = 'RESPONSE_JSON';
		public static const RESPONSE_STRING		: String = 'RESPONSE_STRING';
		public static const RESPONSE_NOTIFY		: String = 'RESPONSE_NOTIFY';
		
		private var _uid		: uint;
		private var _session	: int;
		private var _retFunc	: Object;
		
		public function mySocket(uid: uint, session: int,
								 host: String = null, 
								 port: uint = 0) {
			super(host, port);
			_retFunc = new Object();
			_uid = uid;
			_session = session;
			configureListeners();
		}
		
		public function closeConnection(): void {
			writeUTFBytes("shutdown");
			flush();
		}
		
		public function updateAction(actionName: String, set: Boolean): void {
			sendObject({
				method	: 'action',
				params	: {
					action	: actionName,
					value	: (set?1:0)
				}
			})
		}
		
		public function getSessionState(ret: Function): void {
			getData('getState', null, ret);
		}
		
		public function refresh(matrix: Matrix3D, ret: Function): void {
			getData('refresh', matToArray(matrix), ret);
		}
		
		private function configureListeners():void {
			addEventListener(Event.CLOSE, closeHandler);
			addEventListener(Event.CONNECT, connectHandler);
			addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
		}
		
		public function sendObject(object: Object): void {
			writeUTFBytes(JSON.stringify(object));
			flush();
		}
		
		private function responseJSON(json: String): void {
			var data: Object = JSON.parse(json);
			if (data.hasOwnProperty('qid') && _retFunc.hasOwnProperty(data.qid)) { // Это ответ на запрос
				_retFunc[data.qid](data.result);
				delete(_retFunc[data.qid]);
			} else if (data.hasOwnProperty('notify')) 
				doNotify(data);
			dispatchEvent(new ObjectEvent(RESPONSE_JSON, data));
		}
		
		protected function doNotify(data: Object): void {
			dispatchEvent(new ObjectEvent(RESPONSE_NOTIFY, data));
		}
		
		private function responseString(data: String): void {
			dispatchEvent(new ObjectEvent(RESPONSE_STRING, data));
		}
		
		private function readResponse():void {
			var parts: Array = readUTFBytes(bytesAvailable).split(';');
			parts.forEach(function(item: String, i: int, arr: Array): void {
				if (item.substr(0, 1) == '{')
					responseJSON(item);
				else responseString(item);
			});
		}
		
		protected function qidGenerate(): String {
			return (Math.random() * uint.MAX_VALUE).toString(16);
		}
		
		private function closeHandler(event:Event):void {
		}
		
		protected function matToArray(mat: Matrix3D): Array {
			var result: Array = new Array();
			for (var i:int=0; i<16; i++) {
				result.push(mat.rawData[i]);
			}
			return result;
		}
		
		protected function getData(a_method: String, params: Object, retFunc: Function): void {
			var a_qid: String = qidGenerate();
			_retFunc[a_qid] = retFunc;
			sendObject({
				method	: a_method,
				qid		: a_qid,
				params	: params
			})
		}
		
		protected function init(): void {
			getData('init', {
				uid		: _uid,
				session	: _session
			}, doCompleteInit)
		}
		
		protected function doCompleteInit(data: Object): void {
			dispatchEvent(new Event(Event.COMPLETE));
/*			
			var ticCount	: int = 10;
			var matrix		: Matrix3D = new Matrix3D();
			
			var _timer: uif_Timer = new uif_Timer(1000, function(e: TimerEvent): void {
				matrix.appendRotation(12, Vector3D.Y_AXIS);
				
				if (_timer.currentCount == ticCount) {
					closeConnection();
				}
				
				if (Math.random() > 0.4) sendMyState();
				else getSessionState(function(data: Object): void {
					trace(data);
				});
			}, null, ticCount);*/ 			
		}
		
		private function connectHandler(event:Event):void {
			init();
		}
		
		private function ioErrorHandler(event:IOErrorEvent):void {
			trace("ioErrorHandler: " + event);
		}
		
		private function securityErrorHandler(event:SecurityErrorEvent):void {
			trace("securityErrorHandler: " + event);
		}
		
		private function socketDataHandler(event:ProgressEvent):void {
			readResponse();
		}		
	}
}